import os
import json
import subprocess
from datetime import datetime
from src.modules.file_manager import FileManager
from src.utils.logger import log_info, log_error

class MediaProcessor:
    """专门用于媒体处理的日志工具类，提供详细的媒体处理日志功能"""
    
    def __init__(self, startupinfo,logger=None):
        """
        初始化媒体日志工具
        
        :param logger: 外部日志函数，如果提供则使用它
        """
        self.logger = logger
        self.startupinfo = startupinfo  
        self.file_manager = FileManager(logger=logger)
    
    def log_info(self, message, highlight=False):
        """记录信息日志"""
        if self.logger:
            self.logger(message, level="info")
        else:
            log_info(message, highlight=highlight)
    
    def log_warning(self, message):
        """记录警告日志"""
        if self.logger:
            self.logger(message, level="warning")
        else:
            log_info(message, level="warning")
    
    def log_error(self, message):
        """记录错误日志"""
        if self.logger:
            self.logger(message, level="error")
        else:
            log_error(message)
    
    def log_command(self, cmd, operation_name, success=True):
        """记录命令执行信息"""
        status = "成功" if success else "失败"
        cmd_str = " ".join(str(arg) for arg in cmd)
        self.log_info(f"[{operation_name}] 命令{status}: {cmd_str[:200]}{'...' if len(cmd_str) > 200 else ''}")
    
    def log_file_info(self, file_path, file_type="文件"):
        """记录文件基本信息"""
        if not os.path.exists(file_path):
            self.log_error(f"{file_type}不存在: {file_path}")
            return False
            
        size_mb = round(os.path.getsize(file_path) / (1024 * 1024), 2)
        self.log_info(f"{file_type}信息: {file_path}, 大小: {size_mb} MB")
        return True
    
    def log_subtitle_info(self, subtitle_path):
        """详细记录字幕文件信息"""
        if not os.path.exists(subtitle_path):
            self.log_error(f"字幕文件不存在: {subtitle_path}")
            return False
            
        # 基本文件信息
        subtitle_ext = os.path.splitext(subtitle_path)[1].lower()
        subtitle_size = os.path.getsize(subtitle_path)
        self.log_info(f"字幕文件: {subtitle_path}")
        self.log_info(f"字幕格式: {subtitle_ext}, 大小: {subtitle_size} 字节")
        
        # 识别字幕格式
        subtitle_format = "未知"
        if subtitle_ext in ['.srt']:
            subtitle_format = "SRT"
        elif subtitle_ext in ['.vtt']:
            subtitle_format = "WebVTT"
        elif subtitle_ext in ['.ass', '.ssa']:
            subtitle_format = "ASS/SSA"
        else:
            subtitle_format = f"未知 ({subtitle_ext})"
        
        self.log_info(f"字幕格式识别为: {subtitle_format}")
        
        # 读取字幕内容预览
        try:
            encodings = ['utf-8', 'utf-8-sig', 'latin-1', 'gbk', 'big5']
            content_preview = None
            used_encoding = None
            
            for encoding in encodings:
                try:
                    with open(subtitle_path, 'r', encoding=encoding) as f:
                        content = f.read(1000)
                        if content:
                            content_preview = content
                            used_encoding = encoding
                            break
                except:
                    continue
            
            if content_preview:
                self.log_info(f"字幕使用编码: {used_encoding}")
                
                # 显示前几行
                lines = content_preview.split('\n')[:10]
                preview_text = '\n'.join(lines)
                self.log_info(f"字幕内容预览:\n{preview_text}")
                
                # 估算字幕条数
                if subtitle_format == "SRT":
                    with open(subtitle_path, 'r', encoding=used_encoding) as f:
                        content = f.read()
                        count = content.count('\n\n')
                        self.log_info(f"估计字幕条数: 约 {count} 条")
            else:
                self.log_error(f"无法读取字幕内容，可能是不支持的编码格式")
        except Exception as e:
            self.log_error(f"分析字幕文件时出错: {e}")
        
        return True
    
    def log_media_info(self, media_path, media_type="视频"):
        """记录媒体文件信息（视频、音频）"""
        if not os.path.exists(media_path):
            self.log_error(f"{media_type}文件不存在: {media_path}")
            return None
            
        try:
            # 基本文件信息
            size_mb = round(os.path.getsize(media_path) / (1024 * 1024), 2)
            self.log_info(f"{media_type}文件: {media_path}, 大小: {size_mb} MB")
            
            # 使用ffprobe获取媒体信息
            probe_cmd = [
                "ffprobe", 
                "-v", "error",
                "-show_format",
                "-show_streams",
                "-print_format", "json",
                media_path
            ]
            
            result = subprocess.run(
                probe_cmd, 
                startupinfo=self.startupinfo,
                stdout=subprocess.PIPE,
                stderr=subprocess.PIPE,
                universal_newlines=True,
                encoding='utf-8'
            )
            
            if result.returncode != 0:
                self.log_error(f"获取{media_type}信息失败: {result.stderr}")
                return None
                
            # 解析JSON输出
            info = json.loads(result.stdout)
            
            # 记录格式信息
            if "format" in info:
                format_info = info["format"]
                duration = round(float(format_info.get("duration", "0")), 2)
                bitrate = round(int(format_info.get("bit_rate", "0")) / 1000, 2)
                self.log_info(f"{media_type}格式: {format_info.get('format_name')}, 时长: {duration}秒, 比特率: {bitrate} Kbps")
            
            # 记录流信息
            if "streams" in info:
                streams = info["streams"]
                stream_summary = {}
                
                for stream in streams:
                    codec_type = stream.get("codec_type", "unknown")
                    if codec_type not in stream_summary:
                        stream_summary[codec_type] = 0
                    stream_summary[codec_type] += 1
                    
                    # 记录视频轨道详情
                    if codec_type == "video":
                        codec = stream.get("codec_name", "unknown")
                        width = stream.get("width", "?")
                        height = stream.get("height", "?")
                        fps = eval(stream.get("r_frame_rate", "0/1"))
                        self.log_info(f"视频轨道: {codec}, 分辨率: {width}x{height}, FPS: {round(fps, 2)}")
                    
                    # 记录音频轨道详情
                    elif codec_type == "audio":
                        codec = stream.get("codec_name", "unknown")
                        channels = stream.get("channels", "?")
                        sample_rate = stream.get("sample_rate", "?")
                        self.log_info(f"音频轨道: {codec}, 声道: {channels}, 采样率: {sample_rate}Hz")
                    
                    # 记录字幕轨道详情
                    elif codec_type == "subtitle":
                        codec = stream.get("codec_name", "unknown")
                        self.log_info(f"字幕轨道: {codec}")
                
                # 总结所有轨道
                tracks_summary = ", ".join([f"{type}: {count}" for type, count in stream_summary.items()])
                self.log_info(f"{media_type}轨道总结: {tracks_summary}")
                
                return info
            
        except Exception as e:
            self.log_error(f"分析{media_type}文件时出错: {e}")
        
        return None
    
    def log_subtitle_merge_begin(self, video_path, subtitle_path, output_path):
        """记录字幕合并开始"""
        self.log_info("="*50)
        self.log_info(f"开始处理字幕合并", highlight=True)
        timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        self.log_info(f"处理时间: {timestamp}")
        
        # 记录输入输出文件信息
        self.log_info("输入文件信息:")
        self.log_media_info(video_path, "视频")
        self.log_subtitle_info(subtitle_path)
        self.log_info(f"输出路径: {output_path}")
    
    def log_subtitle_merge_result(self, output_path, success=True, message=""):
        """记录字幕合并结果"""
        status = "成功" if success else "失败"
        self.log_info(f"字幕合并{status}: {message}", highlight=True)
        
        if success and os.path.exists(output_path):
            subtitle_info = self.verify_output_subtitles(output_path)
            if subtitle_info:
                self.log_info(f"确认: 输出文件包含字幕轨道")
            else:
                self.log_error("警告: 未检测到字幕轨道，字幕可能没有成功添加")
        
        self.log_info("="*50)
    
    def verify_output_subtitles(self, output_path):
        """验证输出文件是否包含字幕轨道"""
        try:
            verify_cmd = [
                "ffprobe", 
                "-v", "error",
                "-select_streams", "s", 
                "-show_entries", "stream=index,codec_name:stream_tags=language,title", 
                "-of", "json",
                output_path
            ]
            
            result = subprocess.run(
                verify_cmd, 
                startupinfo=self.startupinfo,
                stdout=subprocess.PIPE,
                stderr=subprocess.PIPE,
                universal_newlines=True,
                encoding='utf-8'
            )
            
            if result.returncode != 0:
                self.log_error(f"验证字幕失败: {result.stderr}")
                return None
                
            subtitle_info = json.loads(result.stdout)
            self.log_info(f"字幕验证结果: {json.dumps(subtitle_info, ensure_ascii=False)}")
            
            if subtitle_info.get("streams") and len(subtitle_info["streams"]) > 0:
                return subtitle_info
            
            return None
            
        except Exception as e:
            self.log_error(f"验证字幕时出错: {e}")
            return None
        
        
    def get_video_resolution(self, video_path):
        """
        获取视频分辨率
        
        :param video_path: 视频文件路径
        :return: (width, height) 元组，如果无法获取则返回 None
        """
        if not os.path.exists(video_path):
            self.log_error(f"获取分辨率失败: 文件不存在 - {video_path}")
            return None
            
        try:
            cmd = [
                "ffprobe", 
                "-v", "error", 
                "-select_streams", "v:0", 
                "-show_entries", "stream=width,height", 
                "-of", "csv=s=x:p=0", 
                video_path
            ]
            
            result = subprocess.run(
                cmd, 
                startupinfo=self.startupinfo,
                stdout=subprocess.PIPE,
                stderr=subprocess.PIPE,
                universal_newlines=True,
                encoding='utf-8'
            )
            
            if result.returncode != 0:
                self.log_error(f"获取视频分辨率失败: {result.stderr}")
                return None
                
            resolution = result.stdout.strip()
            if 'x' in resolution:
                width, height = map(int, resolution.split('x'))
                self.log_info(f"视频分辨率: {width}x{height}")
                return (width, height)
            else:
                self.log_error(f"无法解析视频分辨率: {resolution}")
                return None
                
        except Exception as e:
            self.log_error(f"获取视频分辨率时出错: {str(e)}")
            return None

    def get_media_duration(self, media_path):
        """
        获取媒体时长（秒）
        
        :param video_path: 视频文件路径
        :return: 媒体时长（秒），如果无法获取则返回 None
        """
        if not os.path.exists(media_path):
            self.log_error(f"获取时长失败: 文件不存在 - {media_path}")
            return None
            
        try:
            cmd = [
                "ffprobe", 
                "-v", "error", 
                "-show_entries", "format=duration", 
                "-of", "csv=p=0", 
                media_path
            ]
            
            result = subprocess.run(
                cmd, 
                startupinfo=self.startupinfo,
                stdout=subprocess.PIPE,
                stderr=subprocess.PIPE,
                universal_newlines=True,
                encoding='utf-8'
            )
            
            if result.returncode != 0:
                self.log_error(f"获取媒体时长失败: {result.stderr}")
                return None
                
            duration = result.stdout.strip()
            if duration:
                duration_seconds = float(duration)
                self.log_info(f"媒体时长: {duration_seconds:.2f} 秒")
                return duration_seconds
            else:
                self.log_error("无法获取媒体时长")
                return None
                
        except Exception as e:
            self.log_error(f"获取媒体时长时出错: {str(e)}")
            return None

    def get_video_framerate(self, video_path):
        """
        获取视频帧率
        
        :param video_path: 视频文件路径
        :return: 视频帧率，如果无法获取则返回 None
        """
        if not os.path.exists(video_path):
            self.log_error(f"获取帧率失败: 文件不存在 - {video_path}")
            return None
            
        try:
            cmd = [
                "ffprobe", 
                "-v", "error", 
                "-select_streams", "v:0", 
                "-show_entries", "stream=r_frame_rate", 
                "-of", "csv=p=0", 
                video_path
            ]
            
            result = subprocess.run(
                cmd, 
                startupinfo=self.startupinfo,
                stdout=subprocess.PIPE,
                stderr=subprocess.PIPE,
                universal_newlines=True,
                encoding='utf-8'
            )
            
            if result.returncode != 0:
                self.log_error(f"获取视频帧率失败: {result.stderr}")
                return None
                
            framerate = result.stdout.strip()
            if '/' in framerate:
                num, den = map(int, framerate.split('/'))
                if den > 0:
                    fps = num / den
                    self.log_info(f"视频帧率: {fps:.2f} fps")
                    return fps
                
            self.log_error(f"无法解析视频帧率: {framerate}")
            return None
                
        except Exception as e:
            self.log_error(f"获取视频帧率时出错: {str(e)}")
            return None

    def get_audio_streams_count(self, media_path):
        """
        获取媒体文件中的音频流数量
        
        :param media_path: 媒体文件路径
        :return: 音频流数量，如果无法获取则返回 None
        """
        if not os.path.exists(media_path):
            self.log_error(f"获取音频流数量失败: 文件不存在 - {media_path}")
            return None
            
        try:
            cmd = [
                "ffprobe", 
                "-v", "error", 
                "-select_streams", "a", 
                "-show_entries", "stream=index", 
                "-of", "csv=p=0", 
                media_path
            ]
            
            result = subprocess.run(
                cmd, 
                startupinfo=self.startupinfo,
                stdout=subprocess.PIPE,
                stderr=subprocess.PIPE,
                universal_newlines=True,
                encoding='utf-8'
            )
            
            if result.returncode != 0:
                self.log_error(f"获取音频流数量失败: {result.stderr}")
                return None
                
            streams = result.stdout.strip().split('\n')
            count = len(streams) if streams and streams[0] else 0
            self.log_info(f"音频流数量: {count}")
            return count
            
        except Exception as e:
            self.log_error(f"获取音频流数量时出错: {str(e)}")
            return None

    def get_audio_channels(self, media_path):
        """
        获取音频通道数
        
        :param media_path: 媒体文件路径
        :return: 音频通道数，如果无法获取或没有音频则返回 None
        """
        if not os.path.exists(media_path):
            self.log_error(f"获取音频通道失败: 文件不存在 - {media_path}")
            return None
            
        try:
            cmd = [
                "ffprobe", 
                "-v", "error", 
                "-select_streams", "a:0", 
                "-show_entries", "stream=channels", 
                "-of", "csv=p=0", 
                media_path
            ]
            
            result = subprocess.run(
                cmd, 
                startupinfo=self.startupinfo,
                stdout=subprocess.PIPE,
                stderr=subprocess.PIPE,
                universal_newlines=True,
                encoding='utf-8'
            )
            
            if result.returncode != 0:
                self.log_error(f"获取音频通道失败: {result.stderr}")
                return None
                
            channels = result.stdout.strip()
            if channels:
                self.log_info(f"音频通道数: {channels}")
                return int(channels)
            else:
                self.log_info("未检测到音频流")
                return None
                
        except Exception as e:
            self.log_error(f"获取音频通道时出错: {str(e)}")
            return None

    def get_media_info(self, media_path, info_type="all"):
        """
        获取媒体文件的详细信息
        
        :param media_path: 媒体文件路径
        :param info_type: 信息类型，可以是 "all", "video", "audio", "subtitle"
        :return: 包含所请求信息的字典，如果出错则返回 None
        """
        if not os.path.exists(media_path):
            self.log_error(f"获取媒体信息失败: 文件不存在 - {media_path}")
            return None
            
        try:
            # 构建命令以获取JSON格式的媒体信息
            cmd = [
                "ffprobe", 
                "-v", "error",
                "-show_format",
                "-show_streams",
                "-print_format", "json",
                media_path
            ]
            
            result = subprocess.run(
                cmd, 
                startupinfo=self.startupinfo,
                stdout=subprocess.PIPE,
                stderr=subprocess.PIPE,
                universal_newlines=True,
                encoding='utf-8'
            )
            
            if result.returncode != 0:
                self.log_error(f"获取媒体信息失败: {result.stderr}")
                return None
                    
            # 解析JSON输出
            info = json.loads(result.stdout)
            
            # 根据请求的信息类型过滤结果
            if info_type == "all":
                return info
                
            elif info_type in ["video", "audio", "subtitle"]:
                if "streams" in info:
                    filtered_streams = [
                        stream for stream in info["streams"] 
                        if stream.get("codec_type") == info_type
                    ]
                    return {"streams": filtered_streams, "format": info.get("format", {})}
                
            return None
                
        except Exception as e:
            self.log_error(f"获取媒体信息时出错: {str(e)}")
            return None

    def has_audio_stream(self, media_path):
        """
        检查媒体文件是否包含音频流
        
        :param media_path: 媒体文件路径
        :return: True如果包含音频流，否则False
        """
        channels = self.get_audio_channels(media_path)
        return channels is not None and channels > 0
    
    
    # 添加临时文件创建方法
    def create_temp_media_file(self, original_path, suffix="_processed"):
        """创建临时媒体文件"""
        base_name = os.path.basename(original_path)
        name, ext = os.path.splitext(base_name)
        temp_file = self.file_manager.create_temp_file(
            prefix=f"{name}_",
            suffix=f"{suffix}{ext}",
        )
        return temp_file.path